package bitmap

import (
	"bytes"
	"sync"
)

type Bit uint64 //统一bit类型

const BitSize = 64 //每一个bit位存储数据量
const IndexBit = 6 //位置位移数量

type Bitmap []Bit //bitmap

var mux = sync.Mutex{}

var bitsMap [BitSize]Bit

//func init() {
//	for i := 0; i < BitSize; i++ {
//		bitsMap[i] = Bit(0x01) << Bit(i)
//	}
//}


//设置bit
func (b *Bitmap) SetBit(value Bit, stat bool) *Bitmap {
	mux.Lock()
	defer mux.Unlock()
	index, pos := b.ValueToIndexAndPos(value)
	if stat {
		b.UpCapToIndex(index)
		//设置
		(*b)[index] |= Bit(0x01) << pos
	} else {
		//取消
		if index < len(*b) {
			(*b)[index] &^= Bit(0x01) << pos
		}
	}
	return b
}

func (b *Bitmap) Set(value Bit) *Bitmap {
	b.SetBit(value, true)
	return b
}

func (b *Bitmap) Unset(value Bit) *Bitmap {
	b.SetBit(value, false)
	return b
}

func (b *Bitmap) Get(value Bit) bool {
	index, pos := b.ValueToIndexAndPos(value)
	//(*b)[index] &^= Bit(0x01) << pos
	return index < len(*b) && ((*b)[index]&(Bit(0x01)<<pos) != 0)

}

func (b *Bitmap) ValueToIndexAndPos(value Bit) (int, Bit) {
	return int(value >> IndexBit), value % Bit(BitSize)
}

func (b *Bitmap) UpCapToIndex(index int) {
	toIndex := index + 1
	l := len(*b)
	if l < toIndex {
		l2 := 2 * l
		if toIndex < l2 {
			toIndex = l2
		}
		n := make([]Bit, toIndex, toIndex)
		copy(n, *b)
		*b = n
	}
}

func (b *Bitmap) ToString(split ...string) string {
	l := len(*b)
	sl := len(split)
	ss := ""
	if sl > 0 {
		ss = split[0]
	}
	str := ""
	for i := 0; i < l; i++ {
		if i > 0 && sl > 0 {
			str += ss
		}
		str += (*b)[i].ToString()
	}
	return str
}

func (bit *Bit) ToString() string {
	b := &bytes.Buffer{}
	t := *bit
	for i := 0; i < BitSize; i++ {
		if (t & bitsMap[i]) != 0 {
			b.WriteString("1")
		} else {
			b.WriteString("0")
		}
	}
	return b.String()
}
